#ifndef _BOARDSTATE_H_
#define _BOARDSTATE_H_

#include "move.h"
#include <iostream>
#include <cstdlib>
#include <time.h>

#define WHITE		0
#define BLACK		1

enum {
	EMPTY = 0,
	W_KING, W_QUEEN, W_ROOK, W_BISHOP, W_KNIGHT, W_PAWN,
	B_KING, B_QUEEN, B_ROOK, B_BISHOP, B_KNIGHT, B_PAWN
};


class BoardState
{
private:
	int _board[8][8];
	int _helpBoard[8][8]; // used by isCheck
	int _turn; //0 = white's turn, 1 = black's turn
    int _wPawnAdvancedTwo; // white pawn advanced two at this line (0-7)
    int _bPawnAdvancedTwo; // -1 -> not at any line
    int _wKingPosition[2]; // [0] = x-coordinate, [1] = y-coordinate
    int _bKingPosition[2]; // [0] = x-coordinate, [1] = y-coordinate
    int _helpWKingPosition[2]; // used by isCheck
    int _helpBKingPosition[2]; // used by isCheck
	bool _wCastleShortAllowed;
	bool _wCastleLongAllowed;
	bool _bCastleShortAllowed;
	bool _bCastleLongAllowed;

    // returns a clone of the boardstate
    BoardState clone();

    // removes moves that causes chess, thoss are illegal
    void isCheckW(Move *moveList, int *countMoves);
    void isCheckB(Move *moveList, int *countMoves);

    // returns true if black piece in target square
    bool isBlackPiece(int x, int y);

    // returns true if white piece in targat square
    bool isWhitePiece(int x, int y);

    // executes move to helpBoard
    void modifyHelpBoard(const Move &m);

    // generate min_max values for genBestMvoe
    double alphaBetaMax(int alpha, int beta, int depth, BoardState *state);
    double alphaBetaMin(int alpha, int beta, int depth, BoardState *state);
    double evaluate(); // returns value between -999 (black winning) and 999 (white winning)
    int evaluateMaterial(); //evaluates value of material
    int evaluateKingSafety(); //evaluates king safety
    int evaluatePosition(); //evaluate positions of pieces
    int evaluateHorseSpecial(); //evaluates horses specials
    int analyzeGameProgress(); //analyze progress fo the game (int between 1-99)

    // generates leagal moves to white peaces
	void genLegalMovesWKing(Move *moveList, int xOrg, int yOrg, int *countMoves);
	void genLegalMovesWQueen(Move *moveList, int xOrg, int yOrg, int *countMoves);
	void genLegalMovesWBishop(Move *moveList, int xOrg, int yOrg, int *countMoves);
	void genLegalMovesWRook(Move *moveList, int xOrg, int yOrg, int *countMoves);
	void genLegalMovesWKnight(Move *moveList, int xOrg, int yOrg, int *countMoves);
	void genLegalMovesWPawn(Move *moveList, int xOrg, int yOrg, int *countMoves);

	// generates leagal moves to black peaces
	void genLegalMovesBKing(Move *moveList, int xOrg, int yOrg, int *countMoves);
	void genLegalMovesBQueen(Move *moveList, int xOrg, int yOrg, int *countMoves);
	void genLegalMovesBBishop(Move *moveList, int xOrg, int yOrg, int *countMoves);
	void genLegalMovesBRook(Move *moveList, int xOrg, int yOrg, int *countMoves);
	void genLegalMovesBKnight(Move *moveList, int xOrg, int yOrg, int *countMoves);
	void genLegalMovesBPawn(Move *moveList, int xOrg, int yOrg, int *countMoves);

    // 2d tables used by evaluatePosition
    static const int posPawn[8][8];
    static const int posKnight[8][8];
    static const int posBishop[8][8];
    static const int posRook[8][8];
    static const int posQueen[8][8];
    static const int posKing[8][8];

public:
    BoardState();
    virtual ~BoardState();

    // Empties the board.
	void clear();

	// Sets the inital chess BoardState and white to move.
	void initPos();

	// returns true if player of chosen color should accept a draw
    bool acceptDrawAs(int playerColor);

	// Print BoardState in ASCII for testing purposes.
	void print() const;

	// Update BoardState with given move. We can assume
	// that given move is legal
	//returns true if a piece was captured
	bool execMove(const Move &m);

	// Generate all the legal moves in current BoardState
	// Returns # moves found. Returning 0 means
	// there are no legal moves; the game has ended
	int genLegalMoves(Move *moveList);

	// use AI to generate the best possible move
	Move genBestMove(int depth);

	//setters and getters
	void setTurn(int color);
	int getTurn();

	// Returns piece on the specified square
    int getPiece(int x, int y);

};

#endif // _BOARDSTATE_H_
